/********************************************************************************
 * @file    timer_storage.c
 * @brief   定时器存储
 * 
 * @author  nzttj
 * @date    2025-04-02
 * @version 1.0
 * 
 * Copyright (C) 2025 nzttj
 * 
 * 本软件使用 GNU 通用公共许可证 (GPL) 第 3 版授权。
 * 
 * 您可以自由使用、修改、分发本软件，但必须遵守以下条件：
 * 1. 源代码必须开放，且您修改后的代码也必须以 GPL 许可证发布。
 * 2. 发布或分发本软件时，必须附带本许可证，并提供源代码或获取源代码的方式。
 * 
 * 本软件按"原样"提供，不附带任何担保，使用风险由用户自行承担。
 * 
 ********************************************************************************/

#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"
#include "timer_storage.h"

/** @brief 存储命名空间 */
#define STORAGE_NAMESPACE "smart_timer"

/** @brief 存储键名 */
#define STORAGE_KEY "timers"

static const char *TAG = "timer_storage";

/** @brief NVS句柄 */
static nvs_handle_t s_nvs_handle;

/**
 * @brief 初始化NVS存储系统
 * 
 * 该函数完成以下初始化工作：
 * 1. 初始化NVS Flash
 * 2. 如果需要，擦除并重新初始化NVS分区
 * 3. 打开NVS命名空间
 * 
 * @return timer_err_t 操作结果
 */
static timer_err_t nvs_storage_init(void)
{
    if (s_nvs_handle) {
        return TIMER_ERR_INVALID_STATE;
    }

    // XXX初始化NVS Flash

    esp_err_t err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &s_nvs_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to open NVS handle: %d", err);
        return TIMER_ERR_STORAGE;
    }

    return TIMER_OK;
}

/**
 * @brief 保存定时器配置到NVS存储
 * 
 * @param timers 定时器配置数组
 * @param count 定时器数量
 * @return timer_err_t 操作结果
 */
static timer_err_t nvs_storage_save(const timer_config_t *timers, uint8_t count)
{
    if (!s_nvs_handle) {
        return TIMER_ERR_INVALID_STATE;
    }

    if (!timers && count > 0) {
        return TIMER_ERR_INVALID_ARG;
    }

    esp_err_t err = nvs_set_blob(s_nvs_handle, STORAGE_KEY, timers, count * sizeof(timer_config_t));
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write timers to NVS: %d", err);
        return TIMER_ERR_STORAGE;
    }

    err = nvs_commit(s_nvs_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to commit NVS changes: %d", err);
        return TIMER_ERR_STORAGE;
    }

    return TIMER_OK;
}

/**
 * @brief 从NVS存储加载定时器配置
 * 
 * @param timers 定时器配置数组
 * @param count 输入时表示数组大小，输出时表示实际加载的定时器数量
 * @param max_count 最大允许加载的定时器数量
 * @return timer_err_t 操作结果
 */
static timer_err_t nvs_storage_load(timer_config_t *timers, uint8_t *count, uint8_t max_count)
{
    if (!s_nvs_handle) {
        return TIMER_ERR_INVALID_STATE;
    }

    if (!timers || !count || max_count == 0) {
        return TIMER_ERR_INVALID_ARG;
    }

    size_t required_size = 0;
    esp_err_t err = nvs_get_blob(s_nvs_handle, STORAGE_KEY, NULL, &required_size);
    if (err == ESP_ERR_NVS_NOT_FOUND) {
        ESP_LOGW(TAG, "No stored timers found");
        *count = 0;
        return TIMER_OK;
    } else if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to get stored timers size: %d", err);
        return TIMER_ERR_STORAGE;
    }

    if (required_size == 0 || required_size % sizeof(timer_config_t) != 0) {
        ESP_LOGE(TAG, "Invalid stored data size: %d", required_size);
        return TIMER_ERR_STORAGE;
    }

    uint8_t stored_count = required_size / sizeof(timer_config_t);
    if (stored_count > max_count) {
        ESP_LOGE(TAG, "Stored timer count (%d) exceeds maximum (%d)", stored_count, max_count);
        return TIMER_ERR_FULL;
    }

    err = nvs_get_blob(s_nvs_handle, STORAGE_KEY, timers, &required_size);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read timers from NVS: %d", err);
        return TIMER_ERR_STORAGE;
    }

    *count = stored_count;
    ESP_LOGI(TAG, "Successfully loaded %d timers", stored_count);
    return TIMER_OK;
}

/**
 * @brief 反初始化NVS存储系统
 * 
 * @return timer_err_t 操作结果
 */
static timer_err_t nvs_storage_deinit(void)
{
    if (!s_nvs_handle) {
        return TIMER_ERR_INVALID_STATE;
    }

    nvs_close(s_nvs_handle);
    s_nvs_handle = 0;

    // XXX反初始化NVS Flash

    return TIMER_OK;
}

/**
 * @brief NVS存储实现实例
 * 
 * 提供基于ESP32 NVS的定时器配置存储实现
 */
const timer_storage_t nvs_storage = {
    .init = nvs_storage_init,
    .deinit = nvs_storage_deinit,
    .save_timers = nvs_storage_save,
    .load_timers = nvs_storage_load
}; 